package sy.util.base;

import java.math.BigDecimal;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;

/**
 * 
 * 为HQL添加条件和排序还有分页信息
 * 
 * 查询规则：
 * 
 * 查询条件分成4段，每段直接用下划线_分割；要以Q_开头，第二断是属性，如果是本类属性，请加上t.；第三段是操作符；第四段是值的类型
 * 
 * Q_t.id_IN_S = 1,2,3 =>意思就是查询t.id in ('1','2','3')的数据
 * 
 * Q_t.name_LK_S = 孙 =>意思就是查询t.name like “%%孙%%”的数据
 * 
 * 可使用的类型缩写
 * 
 * S:String L:Long I:Integer D:Date ST:Short BD:BigDecimal FT:Float
 * 
 * 可使用的操作符缩写
 * 
 * // EQ 相等 // NE 不等 // LT 小于 // GT 大于 // LE 小于等于 // GE 大于等于 // LK 模糊 // RLK 右模糊 // LLK 左模糊// IN 包含// NOTIN不包含
 * 
 * @author 孙宇
 * 
 */
public class QueryFilter {

	private HttpServletRequest request;// 为了获取request里面传过来的动态参数
	private Map<String, Object> params = new HashMap<String, Object>();// 条件参数
	private StringBuilder where = new StringBuilder();// where条件
	private StringBuilder sortAndOrder = new StringBuilder();// 排序条件
	private String sort = "";// 排序字段
	private String order = "desc";// asc/desc
	private Integer page;// 要查找第几页的内容
	private Integer rows;// 查找多少条记录
	private Long total;// 查询了多少条记录

	/**
	 * 获得总记录数
	 * 
	 * @return
	 */
	public Long getTotal() {
		return total;
	}

	/**
	 * 设置总记录数
	 * 
	 * @param total
	 */
	public void setTotal(Long total) {
		this.total = total;
	}

	/**
	 * 获得要查询第几页
	 * 
	 * @return
	 */
	public Integer getPage() {
		return page;
	}

	/**
	 * 设置要查询第几页
	 * 
	 * @param page
	 */
	public void setPage(Integer page) {
		this.page = page;
	}

	/**
	 * 获得每页显示记录数
	 * 
	 * @return
	 */
	public Integer getRows() {
		return rows;
	}

	/**
	 * 设置每页显示记录数
	 * 
	 * @param rows
	 */
	public void setRows(Integer rows) {
		this.rows = rows;
	}

	/**
	 * 空构造
	 */
	public QueryFilter() {

	}

	/**
	 * 使用request构造QueryFilter
	 * 
	 * @param request
	 */
	public QueryFilter(HttpServletRequest request) {
		Enumeration<String> names = request.getParameterNames();
		while (names.hasMoreElements()) {
			String name = names.nextElement();
			String value = request.getParameter(name);
			if (name.equals("page")) {
				this.setPage(Integer.valueOf(value));
			} else if (name.equals("rows")) {
				this.setRows(Integer.valueOf(value));
			} else if (name.equals("sort")) {
				this.setSort(value);
			} else if (name.equals("order")) {
				this.setOrder(value);
			} else {
				addFilter(name, value);
			}
		}
	}

	/**
	 * 设置排序字段
	 * 
	 * @param sort
	 */
	public void setSort(String sort) {
		if (!StringUtils.isBlank(sort)) {
			if (!sort.trim().startsWith("t.")) {
				this.sort += "t." + sort;
			}
		}
	}

	/**
	 * 设置排序规则
	 * 
	 * @param order
	 */
	public void setOrder(String order) {
		this.order = order;
	}

	/**
	 * 获得排序字符串
	 * 
	 * @return
	 */
	public String getSortAndOrder() {
		if (!StringUtils.isBlank(sort) && !StringUtils.isBlank(order) && (order.trim().equals("asc") || order.trim().equals("desc"))) {
			return " order by " + sort + " " + order;
		}
		return "";
	}

	/**
	 * 获得参数
	 * 
	 * @return
	 */
	public Map<String, Object> getParams() {
		return this.params;
	}

	/**
	 * 获得where条件
	 * 
	 * @return
	 */
	public String getWhere() {
		return where.toString();
	}

	/**
	 * 添加过滤条件
	 * 
	 * @param column
	 *            字段
	 * @param value
	 *            值
	 */
	public void addFilter(String column, String value) {
		if (!StringUtils.isBlank(column) && column.startsWith("Q_") && !StringUtils.isBlank(value)) {
			String[] command = column.split("_");
			if (command != null && command.length == 4) {
				where.append(" and " + command[1] + " ");
				where.append(" " + getOperator(command[2]) + " ");
				if (StringUtils.equalsIgnoreCase(StringUtils.trim(getOperator(command[2])), "IN") || StringUtils.equalsIgnoreCase(StringUtils.trim(getOperator(command[2])), "NOTIN")) {
					where.append("(");
					String[] vs = value.split(",");
					boolean b = false;
					for (String v : vs) {
						if (b) {
							where.append(",");
						}
						String paramKey = UUID.randomUUID().toString().replace("-", "");
						where.append(":param" + paramKey);
						this.params.put("param" + paramKey, getObjValue(command[3], command[2], v));
						b = true;
					}
					where.append(")");
				} else {
					String paramKey = UUID.randomUUID().toString().replace("-", "");
					where.append(":param" + paramKey);
					this.params.put("param" + paramKey, getObjValue(command[3], command[2], value));
				}
			}
		}
	}

	/**
	 * 获得数据库操作符
	 * 
	 * @param operator
	 * @return
	 */
	private String getOperator(String operator) {
		if (StringUtils.equalsIgnoreCase(operator, "EQ")) {
			return " = ";
		} else if (StringUtils.equalsIgnoreCase(operator, "NE")) {
			return " != ";
		} else if (StringUtils.equalsIgnoreCase(operator, "LT")) {
			return " < ";
		} else if (StringUtils.equalsIgnoreCase(operator, "GT")) {
			return " > ";
		} else if (StringUtils.equalsIgnoreCase(operator, "LE")) {
			return " <= ";
		} else if (StringUtils.equalsIgnoreCase(operator, "GE")) {
			return " >= ";
		} else if (StringUtils.equalsIgnoreCase(operator, "LK") || StringUtils.equalsIgnoreCase(operator, "RLK") || StringUtils.equalsIgnoreCase(operator, "LLK")) {
			return " like ";
		} else if (StringUtils.equalsIgnoreCase(operator, "IN")) {
			return " in ";
		} else if (StringUtils.equalsIgnoreCase(operator, "NOTIN")) {
			return " not in ";
		}
		return "";
	}

	/**
	 * 获得真实类型的值
	 * 
	 * @param columnType
	 * @param operator
	 * @param value
	 * @return
	 */
	private Object getObjValue(String columnType, String operator, String value) {
		if (StringUtils.equalsIgnoreCase(columnType, "S")) {
			if (StringUtils.equalsIgnoreCase(operator, "LK")) {
				value = "%%" + value + "%%";
			} else if (StringUtils.equalsIgnoreCase(operator, "RLK")) {
				value = value + "%%";
			} else if (StringUtils.equalsIgnoreCase(operator, "LLK")) {
				value = "%%" + value;
			}
			return value;
		} else if (StringUtils.equalsIgnoreCase(columnType, "L")) {
			return Long.parseLong(value);
		} else if (StringUtils.equalsIgnoreCase(columnType, "I")) {
			return Integer.parseInt(value);
		} else if (StringUtils.equalsIgnoreCase(columnType, "D")) {
			return DateUtil.stringToDate(value);
		} else if (StringUtils.equalsIgnoreCase(columnType, "ST")) {
			return Short.parseShort(value);
		} else if (StringUtils.equalsIgnoreCase(columnType, "BD")) {
			return BigDecimal.valueOf(Long.parseLong(value));
		} else if (StringUtils.equalsIgnoreCase(columnType, "FT")) {
			return Float.parseFloat(value);
		}
		return "";
	}

}
